import { _decorator, Component, Node, instantiate, Vec2, Vec3, AudioClip, loader, JsonAsset, Prefab, EventTouch, tween, AudioSourceComponent, director } from 'cc';
import { IGameUI } from './GameContract';
import { GamePresenter } from './GamePresenter';
import { GlobalModel } from '../global/GlobalModel';
const { ccclass, property } = _decorator;

@ccclass('GameUI')
export class GameUI extends Component implements IGameUI {

    @property({ type: Node })
    cameraNode: Node = null;
    @property({ type: Node })
    gameNode: Node = null;
    @property({ type: Node })
    playerNode: Node = null;

    private mGamePresenter: GamePresenter = null;
    /**
     * 相机个玩家的x,y,z轴 的坐标
     */
    private xPos: number = 0;
    private yPos: number = 0;
    private zPos: number = 0;
    /**
     * 玩家跳动速度
     */
    private playerJumpSpeed: number = 0.1 / 10;
    /**
     * 创建场景物体的y轴
     */
    private createEnvZ: number = 0;

    /**
    * 点击屏幕坐标
    */
    private touchStartX: number = 0;
    private touchStartY: number = 0;

    /**
     * 存储台子
     */
    private stageArr: Array<Node> = null;


    @property({ type: Node })
    prefab: Node = null;
    @property({ type: Prefab })
    sea0: Prefab = null;
    @property({ type: Prefab })
    sea1: Prefab = null;
    @property({ type: Prefab })
    sea2: Prefab = null;
    @property({ type: Prefab })
    sea3: Prefab = null;

    @property({ type: Prefab })
    treadEffect: Prefab = null;

    private audioSource: AudioSourceComponent = null;
    

    onLoad() {

    }
    start() {
        let self = this;
        this.audioSource = this.node.getComponent(AudioSourceComponent);
        loader.loadRes("music/main/" + GlobalModel.getInstances().getMisicKeyLevel(), AudioClip, (err, audioClip) => {
            if(err) {console.log(err) ;return;}
            self.audioSource.clip = audioClip;
            self.init();
        });
    }
    //
    init(): void {
        this.initData();
        this.initUI();
        this.initEvent();
    }
    //
    initData(): void {
        this.xPos = 0;
        this.yPos = 0;
        this.zPos = 0;
        this.stageArr = new Array();

        this.playerJumpSpeed = 0.1 / 15;
        this.mGamePresenter = new GamePresenter(this);
        this.mGamePresenter.init();
    }
    //
    initUI(): void {
        this.cameraNode.position = new Vec3(this.xPos, this.yPos, this.zPos);
        this.playerNode.position = new Vec3(this.xPos, this.yPos, this.zPos);
        this.initStageNode();
        this.initEnvNode();

    }
    //
    initEvent(): void {
        this.node.on(Node.EventType.TOUCH_START, this.touchStartEvent, this)
        this.node.on(Node.EventType.TOUCH_MOVE, this.touchMoveEvent, this)
        this.node.on(Node.EventType.TOUCH_END, this.touchEndEvent, this)
    }
    //
    initStageNode(): void {
        this.mGamePresenter.initStageNode();
    }
    //
    createStageNode(x: number, y: number, z: number, scale: number): void {
        let node: Node = instantiate(this.prefab);
        node.position = new Vec3(x, y, z);
        node.scale = new Vec3(scale, scale, scale);
        this.gameNode.addChild(node)
        this.stageArr.push(node);
    }
    //
    initEnvNode(): void {
        for (let i = 0; i <= 4; i++) {
            this.createEnvNode();
        }
    }
    //
    createEnvNode(): void {
        // let z: number = this.createEnvZ;
        // let x1: number = -0.626;
        // let x2: number = 0.626;
        // let aa: Array<Prefab> = new Array();
        // aa.push(this.sea0);
        // aa.push(this.sea1);
        // aa.push(this.sea2);
        // aa.push(this.sea3);


        // let node1: Node = instantiate(aa[Math.floor(Math.random() * aa.length)]);
        // node1.position = new Vec3(x1, 0, z);
        // this.gameNode.addChild(node1)


        // let node2: Node = instantiate(aa[Math.floor(Math.random() * aa.length)]);
        // node2.position = new Vec3(x2, 0, z);
        // this.gameNode.addChild(node2);


        // this.createEnvZ -= 1.4;
    }
    private touchStartEvent(event: EventTouch): void {
        if (this.mGamePresenter.getGameState() == 0&&this.audioSource.clip ) {
            this.mGamePresenter.startGame();
            this.audioSource.currentTime=0;
            this.audioSource.play();
        }
        this.touchStartX = event.getLocationX();
        this.touchStartY = event.getLocationY();
    }
    private touchMoveEvent(event: EventTouch): void {
        if (this.mGamePresenter.getGameState() == 1) {
            let _x = event.getLocationX();
            let xOffset: number = this.touchStartX - _x;
            this.xPos -= xOffset * 0.001;

            if (this.xPos <= -0.626 / 3) {
                this.xPos = -0.626 / 3;
            } else if (this.xPos >= 0.626 / 3) {
                this.xPos = 0.626 / 3;
            }
            this.touchStartX = event.getLocationX();
            this.touchStartY = event.getLocationY();
        }
    }
    private touchEndEvent(event: EventTouch): void {

    }
    //
    update(dt: number) {
        if (this.mGamePresenter) {
            this.mGamePresenter.update(dt);
        }
        this.cameraNode.position = new Vec3(0, 0, this.zPos);
        this.playerNode.position = new Vec3(this.xPos, this.yPos, this.zPos);
    }
    refreshPlayerAndCamera(): void {
        this.zPos -= 1 / 60;
        this.refreshEnvNode();
    }
    //
    refreshPlayer(index: number, middleZ: number, nextZ: number): void {
        if (this.playerJumpSpeed > 0) {
            this.yPos = this.yPos + this.playerJumpSpeed;
            if (this.zPos <= middleZ) {
                this.playerJumpSpeed = - 0.1 / 15;
            }
        } else if (this.playerJumpSpeed < 0) {
            this.yPos = this.yPos + this.playerJumpSpeed;
            if (this.zPos <= nextZ) {
                this.zPos = nextZ;
                let stageNode: Node = this.stageArr[index + 1];
                let treadState: number = this.checkTreadIsStage(stageNode);
                if (treadState != 0) {
                    this.mGamePresenter.addPlayerStageIndex();
                    this.playTreadStageEffect(stageNode);
                    this.playTreadStageAnim(stageNode);
                    if (treadState == 2) {   //播放完美踩踏效果

                    }
                    this.playerJumpSpeed = 0.1 / 15;
                    this.yPos = 0;
                    if (this.mGamePresenter.checkIsPass()) {
                        this.gamePassLevel();
                    } else {
                        this.mGamePresenter.addStageNode();
                    }
                } else {
                    this.gameFailLevel();
                }
            }
        }
    }
    //
    refreshCamera(): void {

    }
    //
    refreshEnvNode(): void {
        if (this.zPos - this.createEnvZ <= 1.4 * 4) {
            this.createEnvNode();
        }
    }
    //
    checkTreadIsStage(stageNode: Node): number {
        let type: number = 0;
        let scale: number = stageNode.scale.x;

        let x: number = stageNode.position.x;

        let distance: number = Math.abs(this.xPos-x);
        // console.log(distance,scale)

        if (distance < scale / 10 / 4) {
            type = 2;
        } else if (distance > scale / 10 / 4 && distance < scale / 10) {
            type = 1;
        }
        return type;
    }
    //
    playTreadStageAnim(stageNode: Node): void {
        // let stageNode: Node = this.stageArr[index + 1];
        let nowPos: Vec3 = new Vec3(0, 0, 0);
        Vec3.copy(nowPos, stageNode.position)
        let middlePos: Vec3 = new Vec3(nowPos.x, nowPos.y - 0.07, nowPos.z);


        let nowScale: Vec3 = new Vec3(0, 0, 0);
        Vec3.copy(nowScale, stageNode.scale)
        let middleScale: Vec3 = new Vec3(nowScale.x * 0.9, nowScale.y * 0.9, nowScale.z * 0.9);
        tween(stageNode)
            .to(0.1, { position: middlePos, scale: middleScale })
            .to(0.1, { position: nowPos, scale: nowScale })
            .start();
    }
    //
    playTreadStageEffect(stageNode: Node): void {
        let node: Node = instantiate(this.treadEffect);
        node.position = new Vec3(stageNode.position.x, stageNode.position.y, stageNode.position.z);
        this.gameNode.addChild(node)
    }
    //
    gameFailLevel(): void {
        this.yPos=-0.025;
        this.audioSource.pause();
        this.mGamePresenter.setGameState(2);
        director.loadScene("start");
    }
    //
    reviveGameLevel(): void {
        let index: number = this.mGamePresenter.getPlayerStageIndex();
        let stageNode: Node = this.stageArr[index];
        this.yPos=0;
        this.xPos=stageNode.position.x;
        this.mGamePresenter.setGameState(1);
        this.audioSource.play();
    }
    //
    gamePassLevel(): void {
        this.mGamePresenter.setGameState(3);
        this.scheduleOnce(this.showPassUI, 0.4);
        director.loadScene("start");
    }
    //
    showPassUI(): void {
        this.audioSource.stop();
    }
}
